﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using Common.Logging;
using Quartz;
using Quartz.Collection;
using System.Net.Sockets;
//using ClickForensics.Quartz.Jobs;
using System.IO;
using Quartz.Impl;
using Quartz.Impl.Matchers;
using Quartz.Impl.Triggers;
using XiaoyuI.CrystalQuartz.Domain.Activities;

namespace XiaoyuI.Quartz.WinManager
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            jobGroupsTreeView.AfterSelect += new TreeViewEventHandler(jobGroupsTreeView_AfterSelect);
            jobGroupsTreeView.MouseDown += new MouseEventHandler(jobGroupsTreeView_MouseDown);
        }

        void jobGroupsTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            jobDetailsToggle(false);
            if (e.Node is TriggerNode || e.Node is JobNode)
            {
                btnDeleteJob.Enabled = true;
            }
            else
            {
                btnDeleteJob.Enabled = false;
            }

            if (e.Node is JobNode)
            {
                btnRunJobNow.Enabled = true;
                propertyGrid1.SelectedObject= ((JobNode)e.Node).Job;
                jobDetailsToggle(true);
            }
            else
            {
                btnRunJobNow.Enabled = false;

            }
            if (e.Node is TriggerNode)
            {
                btnPause.Enabled = true;
                setPauseButtonText();
                propertyGrid1.SelectedObject = ((TriggerNode)e.Node).Trigger;
                jobDetailsToggle(true);
                 
                btnEdit.Enabled = true;
            }
            else
            {
                btnEdit.Enabled = false;
                btnPause.Enabled = false;
            }
        }

        private void setPauseButtonText()
        {
            TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
            QuartzScheduler scheduler = getScheduler(node);
            if (node.Trigger.Status == ActivityStatus.Paused)
            {
                btnPause.Text = "Resume";
            }
            else
            {
                btnPause.Text = "Pause";
            }
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (ServerConnectForm form = new ServerConnectForm())
            {
                form.ShowDialog();
                if (!form.Cancelled)
                {
                    try
                    {
                        QuartzScheduler scheduler = new QuartzScheduler(form.Server, form.Port, form.Scheduler);
                        serverConnectStatusLabel.Text = string.Format("Connected to {0}", scheduler.Address);
                        jobsToolStripMenuItem.Enabled = true;
                        loadJobGroups(scheduler);
                        updateRunningJobs();
                    }
                    catch (SocketException ex)
                    {
                        ErrorDialog dialog = new ErrorDialog();
                        dialog.Message = string.Format("Unable to connect to scheduler {0} on {1}:{2}", form.Scheduler, form.Server, form.Port);
                        dialog.Description = ex.Message;
                        dialog.ShowDialog();
                    }
                }
                form.Close();
            }
        }

        private void loadJobGroups(QuartzScheduler scheduler)
        {

            try
            {
                this.Cursor = Cursors.WaitCursor;

                jobDetailsToggle(false);

                SchedulerNode schedulerNode = new SchedulerNode(scheduler);
                if (jobGroupsTreeView.Nodes.ContainsKey(schedulerNode.Name))
                {
                    jobGroupsTreeView.Nodes.RemoveByKey(schedulerNode.Name);
                }
              
                schedulerNode.ContextMenuStrip = ctxScheduler;
                jobGroupsTreeView.Nodes.Add(schedulerNode);
                TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Job Groups");
                var schedulerData = scheduler.GetSchedulerData();
                if (schedulerData != null)
                {
                    if (schedulerData.JobGroups.Any())
                    {
                        foreach (var jobGroup in schedulerData.JobGroups)
                        {
                            TreeNode jobGroupNode = jobGroupsNode.Nodes.Add(jobGroup.Name);
                            TreeNode jobsNode = jobGroupNode.Nodes.Add("Jobs");
                            addJobNodes(jobsNode,jobGroup);
                        }
                    }
                }

                

                jobGroupsTreeView.Nodes[0].Expand();
                jobGroupsNode.Expand();

                StripStatusLabel_Job_Groups.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss");
                
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }


        }
        private void jobDetailsToggle(bool isVisible)
        {
            if (isVisible == false)
            {
                propertyGrid1.SelectedObject = null ;
            }
        }

        void jobGroupsTreeView_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                TreeNode node = jobGroupsTreeView.GetNodeAt(e.X, e.Y);
                if (node != null)
                {
                    jobGroupsTreeView.SelectedNode = node;
                    ctxScheduler.Show(jobGroupsTreeView, e.Location);
                }
            }
        }

        private void addJobNodes(TreeNode node, JobGroupData groupData)
        {
            string group = node.Parent.Text;
            foreach (var job in groupData.Jobs)
            {
                JobNode jobNode = new JobNode(job);
                node.Nodes.Add(jobNode);
                addTriggerNodes(jobNode,job.Triggers);
            }
        }

        private void addTriggerNodes(TreeNode treeNode, IList<TriggerData> triggers)
        {
           
            TreeNode triggersNode = treeNode.Nodes.Add("Triggers");
            foreach (var trigger in triggers)
            {
                TriggerNode node = new TriggerNode(trigger);
                triggersNode.Nodes.Add(node);
               
            }

        }

       

        private void updateRunningJobs()
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;

                timer_Refresh_Running_Jobs.Stop();

                listView_RunningJobs.Items.Clear();
                foreach (var quartzScheduler in getAllSchedulers())
                {
                    DataTable table = quartzScheduler.GetRunningJobs();
                    foreach (DataRow row in table.Rows)
                    {
                        ListViewItem item =
                            new ListViewItem(new string[] { Convert.ToString(row["JobName"]), Convert.ToString(row["Runtime"]) });
                        listView_RunningJobs.Items.Add(item);
                    }
                }
                StripStatusLabel_Jobs_Refresh_date.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss");

                int timer_was = timer_Refresh_Running_Jobs.Interval;
                timer_Refresh_Running_Jobs.Interval = timer_was + 1;
                timer_Refresh_Running_Jobs.Interval = timer_was;

                timer_Refresh_Running_Jobs.Start();
            }
            catch (Exception ex)
            {
                _Log.Error("Unable to load running jobs", ex);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private List<QuartzScheduler> getAllSchedulers()
        {
            List<QuartzScheduler> schedulers = new List<QuartzScheduler>();
            foreach (var node in jobGroupsTreeView.Nodes)
            {
                schedulers.Add(((SchedulerNode)node).Scheduler);
            }
            return schedulers;
        }

        private void addJobToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddJobForm form = new AddJobForm();
            form.ShowDialog();
            if (form.JobDetail != null && form.Trigger != null)
            {
                QuartzScheduler scheduler = getSelectedScheduler();
                scheduler.GetScheduler().ScheduleJob(form.JobDetail, form.Trigger);
                loadJobGroups(scheduler);
            }
        }

        private QuartzScheduler getSelectedScheduler()
        {
            TreeNode node = jobGroupsTreeView.SelectedNode;
            return getScheduler(node);
        }

        private void btnRefreshRunningJobs_Click(object sender, EventArgs e)
        {
            updateRunningJobs();
        }

        private void btnRefreshJobGroups_Click(object sender, EventArgs e)
        {
            List<QuartzScheduler> schedulers = getAllSchedulers();
            foreach (var quartzScheduler in schedulers)
            {
                loadJobGroups(quartzScheduler);
            }
        }

        private void btnRunJobNow_Click(object sender, EventArgs e)
        {
            JobNode node = (JobNode)jobGroupsTreeView.SelectedNode;
            QuartzScheduler scheduler = getScheduler(node);
            scheduler.GetScheduler().TriggerJob(new JobKey(node.Job.Name));
        }

        private void btnDeleteJob_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = jobGroupsTreeView.SelectedNode;
            if (selectedNode is JobNode)
            {
                JobNode node = (JobNode)jobGroupsTreeView.SelectedNode;
                QuartzScheduler scheduler = getScheduler(selectedNode);
                scheduler.GetScheduler().DeleteJob(new JobKey(node.Job.Name));
                jobGroupsTreeView.SelectedNode.Remove();

            }
            if (selectedNode is TriggerNode)
            {
                QuartzScheduler scheduler = getScheduler(selectedNode);
               // scheduler.GetScheduler().UnscheduleJob(((TriggerNode)selectedNode).Trigger.Key);
            }
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
            QuartzScheduler scheduler = getScheduler(node);
            var trigger = new TriggerKey(node.Trigger.Name);
            if (scheduler.GetScheduler().GetTriggerState(trigger) == TriggerState.Paused)
            {
                scheduler.GetScheduler().ResumeTrigger(trigger);
            }
            else
            {
                scheduler.GetScheduler().PauseTrigger(trigger);
            }
            setPauseButtonText();
        }

        private QuartzScheduler getScheduler(TreeNode node)
        {
            if (node is SchedulerNode)
            {
                return ((SchedulerNode)node).Scheduler;
            }
            return getScheduler(node.Parent);
        }

        private void btnEdit_Click(object sender, EventArgs e)
        {
            TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode;
            QuartzScheduler scheduler = getScheduler(node);
            AddJobForm form = new AddJobForm(node);
            form.ShowDialog();
            if (form.JobDetail != null && form.Trigger != null)
            {
              //  scheduler.GetScheduler().RescheduleJob(node.Trigger.Key, form.Trigger);
                loadJobGroups(scheduler);
            }
        }

        private void backupToolStripMenuItem_Click(object sender, EventArgs e)
        {
            QuartzScheduler scheduler = ((SchedulerNode)((TreeView)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl).SelectedNode).Scheduler;
            FileDialog dialog = new SaveFileDialog();
            dialog.ShowDialog();
            FileInfo file = new FileInfo(dialog.FileName);
            scheduler.BackupToFile(file);
        }

        private void timer_Refresh_Running_Jobs_Tick(object sender, EventArgs e)
        {
            updateRunningJobs();
        }

       

        
        private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        
       
    }
}

